#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_start  = false;
    m_pause  = false;
    m_select = -1;
    m_path   = ".";

    init();

    m_echo = ilog4x_echo::create();
    m_echo->setEcho(this);
    m_echo->setInterval(200);

    connect(this, SIGNAL(sgLogEchoLine(const QString&, const int&)),
            this, SLOT(on_log_echo(const QString&, const int&)));
}

MainWindow::~MainWindow()
{
    if (m_start)
    {
        m_echo->stop();
        m_start = false;
    }
    delete ui;
}

void
MainWindow::init()
{
    m_levels = 0x3F;

    ui->comboBox_interval->setCurrentIndex(1);
    ui->radioButton_all->setChecked(true);
    ui->checkBox_trace->setCheckState(Qt::CheckState::Checked);
    ui->checkBox_debug->setCheckState(Qt::CheckState::Checked);
    ui->checkBox_info->setCheckState(Qt::CheckState::Checked);
    ui->checkBox_warn->setCheckState(Qt::CheckState::Checked);
    ui->checkBox_error->setCheckState(Qt::CheckState::Checked);
    ui->checkBox_fatal->setCheckState(Qt::CheckState::Checked);

    ui->pushButton_refresh->setDisabled(true);
}

void
MainWindow::echo(const string& line, int level, const vector<log4x_hl_t>& hlsearch)
{
    QString str = QString(line.c_str());
    emit sgLogEchoLine(str, level);
}

void
MainWindow::filter()
{
    if (!m_start)
    {
        return;
    }

    string keyword = ui->lineEdit_keyword->text().toStdString();
    m_echo->filter(m_levels, keyword);
}

void
MainWindow::checkBox(bool checked, int level)
{
    m_levels = checked ? (m_levels | 1 << level) : (m_levels & ~(1 << level));

    if (!checked)
    {
        ui->radioButton_all->setChecked(false);
    }

    filter();
}

void
MainWindow::restart()
{
    if (!m_start)
    {
        return;
    }

    if (m_pause)
    {
        on_pushButton_pause_clicked();
    }

    m_echo->stop();
    m_start = false;

    on_pushButton_start_clicked();
}

void
MainWindow::on_log_echo(const QString& line, const int& level)
{
    ui->textEdit_echo->append(line);
}

void
MainWindow::on_pushButton_selectFile_clicked()
{
    QFileDialog *fileDialog = new QFileDialog(this);

    fileDialog->setWindowTitle(tr("选择文件"));
    fileDialog->setDirectory(".");

    fileDialog->setFileMode(QFileDialog::ExistingFiles);
    fileDialog->setViewMode(QFileDialog::Detail);

    QStringList fileNames;
    if (fileDialog->exec())
    {
        fileNames = fileDialog->selectedFiles();
    }

    for (auto file : fileNames)
    {
        ui->lineEdit_fullPath->setText(file);
    }

    string fullPath = ui->lineEdit_fullPath->text().toStdString();
    string pname    = "";
    vector<string> pids, keys;
    if (m_echo->getInfo(fullPath, m_path, pname, pids, keys) < 0)
    {
        QMessageBox::information(this, tr("get informations faild!"), tr("invalidate file!"));
        return;
    }

    ui->comboBox_pnames->clear();
    ui->comboBox_pnames->addItem(QString(pname.c_str()));
    ui->comboBox_pnames->setDisabled(true);

    ui->comboBox_pids->clear();
    for (size_t i = 0; i < pids.size(); ++i)
    {
        QString pid = QString(pids[i].c_str());
        ui->comboBox_pids->addItem(pid);
    }

    ui->comboBox_keys->clear();
    ui->comboBox_keys->addItem("all");
    for (size_t i = 0; i < keys.size(); ++i)
    {
        QString key = QString(keys[i].c_str());
        ui->comboBox_keys->addItem(key);
    }

    m_select = 0;
}

void MainWindow::on_pushButton_selectDir_clicked()
{
    QString dir = QFileDialog::getExistingDirectory(
                      this, "选择日志目录",
                      QString(m_path.c_str()));
    if (dir.isEmpty())
    {
        return;
    }
    else
    {
        dir += "/";
    }
    ui->lineEdit_logDir->setText(dir);

    string logDir = dir.toStdString();
    vector<string> pnames;
    m_mpids.clear();
    m_mkeys.clear();

    if (m_echo->getInfo(logDir, pnames, m_mpids, m_mkeys) < 0)
    {
        QMessageBox::information(this, tr("get informations faild!"), tr("invalidate directory!"));
        return;
    }

    if (pnames.empty())
    {
        QMessageBox::information(this, tr("get process names faild!"), tr("the directory have no log files!"));
        return;
    }

    m_path = logDir;

    ui->comboBox_pnames->clear();
    ui->comboBox_pnames->setDisabled(false);
    for (size_t i = 0; i < pnames.size(); ++i)
    {
        QString pname = QString(pnames[i].c_str());
        ui->comboBox_pnames->addItem(pname);
    }
    ui->comboBox_pnames->setCurrentIndex(0);

    ui->comboBox_pids->clear();
    vector<string> &pids = m_mpids[pnames[0]];
    for (size_t i = 0; i < pids.size(); ++i)
    {
        QString pid = QString(pids[i].c_str());
        ui->comboBox_pids->addItem(pid);
    }

    ui->comboBox_keys->clear();
    ui->comboBox_keys->addItem("all");
    vector<string> &keys = m_mkeys[pnames[0]];
    for (size_t i = 0; i < keys.size(); ++i)
    {
        QString key = QString(keys[i].c_str());
        ui->comboBox_keys->addItem(key);
    }

    m_select = 1;
}

void
MainWindow::on_pushButton_start_clicked()
{
    if (m_start)
    {
        if (m_pause)
        {
            on_pushButton_pause_clicked();
        }

        m_echo->stop();
        m_start = false;
        ui->pushButton_start->setText("启动");
    }
    else
    {
        string pname = ui->comboBox_pnames->currentText().toStdString();
        string pid   = ui->comboBox_pids->currentText().toStdString();
        string key   = ui->comboBox_keys->currentText().toStdString();
        key = ("all" == key) ? "" : key;

        string log = m_echo->getFileName(m_path, pname, pid, key);
        if (m_echo->start(log) < 0)
        {
            QMessageBox::information(this, tr("start echo faild!"), tr("invalidate log file!"));
            return;
        }
        m_start = true;

        ui->pushButton_start->setText("停止");

        filter();
    }
}

void MainWindow::on_pushButton_reset_clicked()
{
    init();

    if (0 == m_select)
    {
        string fullPath = ui->lineEdit_fullPath->text().toStdString();
        string pname    = "";
        vector<string> pids, keys;
        if (m_echo->getInfo(fullPath, m_path, pname, pids, keys) < 0)
        {
            QMessageBox::information(this, tr("get information faild!"), tr("invalidate file!"));
            return;
        }

        ui->comboBox_pnames->clear();
        ui->comboBox_pnames->addItem(QString(pname.c_str()));
        ui->comboBox_pnames->setDisabled(true);

        ui->comboBox_pids->clear();
        for (size_t i = 0; i < pids.size(); ++i)
        {
            QString pid = QString(pids[i].c_str());
            ui->comboBox_pids->addItem(pid);
        }

        ui->comboBox_keys->clear();
        ui->comboBox_keys->addItem("all");
        for (size_t i = 0; i < keys.size(); ++i)
        {
            QString key = QString(keys[i].c_str());
            ui->comboBox_keys->addItem(key);
        }
    }
    else if (1 == m_select)
    {
        string logDir = ui->lineEdit_logDir->text().toStdString();
        vector<string> pnames;
        m_mpids.clear();
        m_mkeys.clear();

        if (m_echo->getInfo(logDir, pnames, m_mpids, m_mkeys) < 0)
        {
            QMessageBox::information(this, tr("get informations faild!"), tr("invalidate directory!"));
            return;
        }

        if (pnames.empty())
        {
            QMessageBox::information(this, tr("get process names faild!"), tr("the directory have no log files!"));
            return;
        }

        m_path = logDir;

        ui->comboBox_pnames->clear();
        ui->comboBox_pnames->setDisabled(false);
        for (size_t i = 0; i < pnames.size(); ++i)
        {
            QString pname = QString(pnames[i].c_str());
            ui->comboBox_pnames->addItem(pname);
        }
        ui->comboBox_pnames->setCurrentIndex(0);

        ui->comboBox_pids->clear();
        vector<string> &pids = m_mpids[pnames[0]];
        for (size_t i = 0; i < pids.size(); ++i)
        {
            QString pid = QString(pids[i].c_str());
            ui->comboBox_pids->addItem(pid);
        }

        ui->comboBox_keys->clear();
        ui->comboBox_keys->addItem("all");
        vector<string> &keys = m_mkeys[pnames[0]];
        for (size_t i = 0; i < keys.size(); ++i)
        {
            QString key = QString(keys[i].c_str());
            ui->comboBox_keys->addItem(key);
        }
    }
    else
    {

    }
}

void
MainWindow::on_radioButton_all_clicked(bool checked)
{
    m_levels = checked ? 0x3F : 0;

    if (checked)
    {
        ui->checkBox_trace->setCheckState(Qt::CheckState::Checked);
        ui->checkBox_debug->setCheckState(Qt::CheckState::Checked);
        ui->checkBox_info->setCheckState(Qt::CheckState::Checked);
        ui->checkBox_warn->setCheckState(Qt::CheckState::Checked);
        ui->checkBox_error->setCheckState(Qt::CheckState::Checked);
        ui->checkBox_fatal->setCheckState(Qt::CheckState::Checked);
    }
    else
    {
        ui->checkBox_trace->setCheckState(Qt::CheckState::Unchecked);
        ui->checkBox_debug->setCheckState(Qt::CheckState::Unchecked);
        ui->checkBox_info->setCheckState(Qt::CheckState::Unchecked);
        ui->checkBox_warn->setCheckState(Qt::CheckState::Unchecked);
        ui->checkBox_error->setCheckState(Qt::CheckState::Unchecked);
        ui->checkBox_fatal->setCheckState(Qt::CheckState::Unchecked);
    }

    filter();
}

void
MainWindow::on_checkBox_trace_clicked(bool checked)
{
    checkBox(checked, LOG_LEVEL_TRACE);
}

void
MainWindow::on_checkBox_debug_clicked(bool checked)
{
    checkBox(checked, LOG_LEVEL_DEBUG);
}

void
MainWindow::on_checkBox_info_clicked(bool checked)
{
    checkBox(checked, LOG_LEVEL_INFO);
}

void MainWindow::on_checkBox_warn_clicked(bool checked)
{
    checkBox(checked, LOG_LEVEL_WARN);
}

void
MainWindow::on_checkBox_error_clicked(bool checked)
{
    checkBox(checked, LOG_LEVEL_ERROR);
}

void
MainWindow::on_checkBox_fatal_clicked(bool checked)
{
    checkBox(checked, LOG_LEVEL_FATAL);
}

void
MainWindow::on_comboBox_interval_currentIndexChanged(int index)
{
    if (!m_start)
    {
        return;
    }

    int interval = 200;
    switch (index)
    {
    case 0:
        interval = 100;
        break;
    case 1:
        interval = 200;
        break;
    case 2:
        interval = 500;
        break;
    case 3:
        interval = 1000;
        break;
    case 4:
        interval = 2000;
        break;
    case 5:
        interval = 5000;
        break;
    default:
        interval = 200;
        break;
    }

    m_echo->setInterval(interval);
}

void
MainWindow::on_pushButton_pause_clicked()
{
    if (!m_start)
    {
        return;
    }

    m_pause = !m_pause;
    m_echo->pause(m_pause);

    if (m_pause)
    {
        ui->pushButton_pause->setText("继续");
        ui->pushButton_refresh->setDisabled(false);
    }
    else
    {
        ui->pushButton_pause->setText("暂停");
        ui->pushButton_refresh->setDisabled(true);
    }
}

void MainWindow::on_pushButton_refresh_clicked()
{
    if (!m_pause)
    {
        return;
    }

    m_echo->refresh();
}

void
MainWindow::on_pushButton_clear_clicked()
{
    ui->textEdit_echo->clear();
}

void
MainWindow::on_lineEdit_keyword_textChanged(const QString &arg1)
{

}

void MainWindow::on_comboBox_pnames_currentIndexChanged(const QString &pname)
{
    if (pname.isEmpty())
    {
        return;
    }

    if (1 != m_select)
    {
        return;
    }

    ui->comboBox_pids->clear();
    vector<string> &pids = m_mpids[pname.toStdString()];
    for (size_t i = 0; i < pids.size(); ++i)
    {
        QString pid = QString(pids[i].c_str());
        ui->comboBox_pids->addItem(pid);
    }

    ui->comboBox_keys->clear();
    ui->comboBox_keys->addItem("all");
    vector<string> &keys = m_mkeys[pname.toStdString()];
    for (size_t i = 0; i < keys.size(); ++i)
    {
        QString key = QString(keys[i].c_str());
        ui->comboBox_keys->addItem(key);
    }
}

void
MainWindow::on_comboBox_pids_currentIndexChanged(const QString &pid)
{
    if (pid.isEmpty())
    {
        return;
    }

    restart();
}

void
MainWindow::on_comboBox_keys_currentIndexChanged(const QString &key)
{
    if (key.isEmpty())
    {
        return;
    }

    restart();
}
